/**
 * 测试读写锁 3个写，5个读；
 * @author: sundx
 * @date: 2020-05-27 19:58:45
 * @Last Modified by: sundx
 * @Last Modified time: 2020-05-27 20:37:22
 */

#include <iostream>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

void *writeTest(void *argv);
void *readTest(void *argv);
pthread_rwlock_t mutex = PTHREAD_RWLOCK_INITIALIZER;
int counter = 0;

int main() {
  pthread_t tid[8];
  int ret;
  int i = 0;
  for (; i < 3; ++i) { //创建写进程
    ret = pthread_create(&tid[i], NULL, writeTest, (void *)i);
    if (ret < 0) {
      std::cout << "pthread_create write failed " << strerror(ret) << std::endl;
    }
  }
  for (; i < 8; ++i) { //创建读进程
    ret = pthread_create(&tid[i], NULL, readTest, (void *)i);
    if (ret < 0) {
      std::cout << "pthread_create read failed " << strerror(ret) << std::endl;
    }
  }
  for (int j = 0; j < 8; ++j) {
    ret = pthread_join(tid[j], nullptr);
    if (ret < 0) {
      std::cout << "pthread_join failed " << strerror(ret) << std::endl;
    }
  }
  pthread_exit(nullptr);
  return 0;
}

void *writeTest(void *argv) {
  int ret;
  long i = (long)argv;
  while (1) {
    ret = pthread_rwlock_wrlock(&mutex); // 加锁
    if (ret < 0) {
      std::cout << "son write lock failed" << strerror(ret) << std::endl;
    }
    // int t = counter;
    usleep(1000);
    std::cout << "write " << i << " " << pthread_self()
              << " counter: " << counter << " ++counter: " << ++counter
              << std::endl;
    ret = pthread_rwlock_unlock(&mutex); // 解锁
    if (ret < 0) {
      std::cout << "son wr unlock failed" << strerror(ret) << std::endl;
    }
    sleep(1);
  }
  return nullptr;
}
void *readTest(void *argv) {
  int ret;
  long i = (long)argv;
  while (1) {
    ret = pthread_rwlock_rdlock(&mutex); // 加锁
    if (ret < 0) {
      std::cout << "son write lock failed" << strerror(ret) << std::endl;
    }
    // std::cout << "read  " << i << " " << pthread_self()
    //           << " counter: " << counter << std::endl;
    printf("read  %d: %lu: %d\n", i, pthread_self(), counter);
    ret = pthread_rwlock_unlock(&mutex); // 解锁
    if (ret < 0) {
      std::cout << "son wr unlock failed" << strerror(ret) << std::endl;
    }
    sleep(1);
  }
  return nullptr;
}